﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OpenSSL.X509;
using OpenSSL.Crypto;
using OpenSSL.Core;
using Sicurezza.Entita;

namespace Sicurezza.Client.Manager
{
    public class X509Manager
    {
        public static string CreateRequest
            (
             RSA key,
             string SubjectC,
             string SubjectO,
             string SubjectOU,
             string SubjectCN,
            string SubjectEmail,
            bool digitalSignature,
            bool keyEncipherment
            )
        {
            string keyUsage = "";
            X509Name subject = new X509Name();
            subject.Country = SubjectC;
            subject.Organization = SubjectO;
            subject.OrganizationUnit = SubjectOU;
            subject.Common = SubjectCN;
            subject.AddEntryByName("subjectAltName", "email:" + SubjectEmail);
            if (digitalSignature && keyEncipherment)
                keyUsage += "digitalSignature,keyEncipherment";
            else
            {
                if (digitalSignature) keyUsage += "digitalSignature";
                if (keyEncipherment) keyUsage += "keyEncipherment";
            }
            if(!string.IsNullOrEmpty(keyUsage))
                subject.AddEntryByName("keyUsage", keyUsage);
            

            CryptoKey k = new CryptoKey(key);


            X509Request r = new X509Request(3, subject, k);
            r.Sign(k, MessageDigest.SHA1);
            

            return r.PEM;

        }


        public static string Decrypt(string certificate)
        {
            throw new NotImplementedException();
        }

        public static bool Check(string certificate)
        {
            throw new NotImplementedException();
        }

        public static void Save(X509Certificate c)
        {
            FileManager.SaveCertificate(c.SerialNumber, c.PEM);
        }

        public static object GetAll()
        {
            string[] paths = FileManager.GetCertificates();
            List<Pair> elements = new List<Pair>();
            Pair p = null;
            X509Certificate c = null;
            for (int i = 0; i < paths.Length; i++)
            {
                p = new Pair();
                p.key = paths[i];
                c = new X509Certificate(new BIO(FileManager.LoadCertificate(paths[i])));
                p.value = c.Subject.ToString();
                elements.Add(p);
            }

            return elements;
        }

        /// <summary>
        /// Torna il certificato dal repository locale
        /// </summary>
        /// <param name="Id"></param>
        /// <returns></returns>
        public static X509Certificate Get(string Id)
        {
            string cert = FileManager.LoadCertificate(Id);
            return new X509Certificate(new BIO(cert));
        }

        public static string GetDN(X509Certificate cert)
        {
            return cert.Subject.ToString();
        }

        public static string GetEmail(X509Certificate cert)
        {
            X509Extension mail = cert.Extensions.FirstOrDefault(x => x.Name.Equals("X509v3 Subject Alternative Name"));

            if (mail != null)
                return mail.ToString().Replace("email:", "");

            return "";
        }

        public static bool IsSignAllowed(X509Certificate cert)
        {
            X509Extension keyUsage = cert.Extensions.FirstOrDefault(x => x.Name.Equals("X509v3 Key Usage"));
            if (keyUsage != null)
                return keyUsage.ToString().Contains("Digital Signature");

            return false;
        }

        public static bool IsEncipherAllowed(X509Certificate cert)
        {
            X509Extension keyUsage = cert.Extensions.FirstOrDefault(x => x.Name.Equals("X509v3 Key Usage"));
            if (keyUsage != null)
                return keyUsage.ToString().Contains("Key Encipherment");

            return false;
        }

        /// <summary>
        /// Torna il certificato dalla CA
        /// </summary>
        /// <param name="serial"></param>
        /// <returns></returns>
        public static X509Certificate Get(int serial)
        {
            string certificate = WSManager.GetCertificate(serial.ToString());
            return new X509Certificate(new BIO(certificate));
        }
    }
}
